package com.ncmem.controller;

import com.google.gson.Gson;
import com.ncmem.down2.database.sql.DnFile;
import com.ncmem.up6.biz.*;
import com.ncmem.up6.database.DBConfig;
import com.ncmem.up6.database.DBFile;
import com.ncmem.up6.database.DbFolder;
import com.ncmem.up6.model.FileInf;
import com.ncmem.up6.sql.*;
import com.ncmem.up6.store.FileBlockWriter;
import com.ncmem.up6.utils.*;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.sql.SQLException;
import java.text.ParseException;
import java.util.List;

/**
 * Created by jmzy on 2021/1/7.
 */
@Controller
public class MgrApi {
    @Autowired
    private HttpServletRequest req;

    @Autowired
    private HttpServletResponse res;

    /**
     * 加载根目录下的数据
     * @param uid
     * @param pid
     * @param pathRel
     * @return
     */
    public String loadRootData(int uid,String pid,String pathRel) throws SQLException, InstantiationException, ParseException, IllegalAccessException {
        List<FileInf> files = SqlTable.build("up6_files").reads(FileInf.build(),
                "f_id,f_pid,f_nameLoc,f_sizeLoc,f_lenLoc,f_time,f_pidRoot,f_fdTask,f_pathSvr,f_pathRel,f_object_key",
                SqlWhere.build()
                        .eq("f_uid",uid)
                        .eq("f_complete",true)
                .eq("f_deleted",false)
                .eq("f_fdChild",false),
                SqlSort.build().desc("f_fdTask").desc("f_time")
        );

        JSONObject o = new JSONObject();
        o.put("count", files.size());
        o.put("code", 0);
        o.put("msg", "");
        o.put("data", JSONArray.fromObject(files.toArray(), JsonDateValueProcessor.build()));

        System.out.println(o.toString());
        return o.toString();
    }

    /**
     * 加载子目录数据
     * @return
     */
    public String loadChildData(int uid,String pid,String pathRel) throws SQLException, InstantiationException, ParseException, IllegalAccessException {
         String pathRelSql = String.format("f_pathRel='%s'+f_nameLoc",pathRel);
        if(ConfigReader.dbType() != DataBaseType.SqlServer)
            pathRelSql = String.format("f_pathRel=CONCAT('%s',f_nameLoc)",pathRel);

        //加载文件列表
        List<FileInf> files = SqlTable.build("up6_files").reads(FileInf.build(),
                "f_id,f_pid,f_nameLoc,f_sizeLoc,f_lenLoc,f_time,f_pidRoot,f_fdTask,f_pathSvr,f_pathRel,f_object_key",
                SqlWhere.build().
                        eq("f_uid",uid).eq("f_complete",true)
                        .eq("f_deleted",false)
                        .eq("f_fdChild",true)
                        .sql("f_pathRel",pathRelSql),
                SqlSort.build().desc("f_fdTask").desc("f_time")
        );

        //加载子目录
        List<FileInf> folders = SqlTable.build("up6_folders").reads(FileInf.build(),
                "f_id,f_nameLoc,f_pid,f_sizeLoc,f_time,f_pidRoot,f_pathRel",
                SqlWhere.build().
                        eq("f_uid",uid)
                        .eq("f_complete",true)
                        .eq("f_deleted",false)
                        .sql("f_pathRel",pathRelSql),
                SqlSort.build().desc("f_time")
        );

        for (FileInf f : folders)
        {
            f.fdTask=true;
            f.fdChild=false;
            files.add(0,f);
        }

        JSONObject o = new JSONObject();
        o.put("count", files.size());
        o.put("code", 0);
        o.put("msg", "");
        o.put("data", JSONArray.fromObject(files.toArray(), JsonDateValueProcessor.build()));

        System.out.println(o.toString());
        return o.toString();
    }

    /**
     * 加载文件列表数据，
     * @param pid 父级ID
     * @param uid 用户ID
     * @param pageSize     页大小
     * @param pageIndex    页索引
     * @return
     */
    @RequestMapping(value="filemgr/data",method = RequestMethod.GET)
    @ResponseBody
    public String data(@RequestParam(value="pid", required=false,defaultValue="")String pid,
                       @RequestParam(value="uid", required=false,defaultValue="")Integer uid,
                       @RequestParam(value="limit", required=false,defaultValue="20")String pageSize,
                       @RequestParam(value="page", required=false,defaultValue="1")String pageIndex,
                       @RequestParam(value="pathRel", required=false,defaultValue="")String pathRel
    ) throws SQLException, InstantiationException, ParseException, IllegalAccessException {
        pathRel = PathTool.url_decode(pathRel);
        if(!pathRel.endsWith("/")) pathRel+="/";
        //根目录
        if (StringUtils.equals(pathRel,"/") ) return  this.loadRootData(uid,pid,pathRel);
        else return this.loadChildData(uid,pid,pathRel);
    }

    /**
     * 搜索文件列表数据，
     * @param pid 父级ID
     * @param uid 用户ID
     * @param pageSize     页大小
     * @param pageIndex    页索引
     * @return
     */
    @RequestMapping(value="filemgr/search",method = RequestMethod.GET)
    @ResponseBody
    public String search(@RequestParam(value="pid", required=false,defaultValue="")String pid,
                       @RequestParam(value="uid", required=false,defaultValue="0")Integer uid,
                       @RequestParam(value="limit", required=false,defaultValue="")String pageSize,
                       @RequestParam(value="page", required=false,defaultValue="")String pageIndex,
                       @RequestParam(value="pathRel", required=false,defaultValue="")String pathRel,
                         @RequestParam(value="key", required=false,defaultValue="")String key
    ) throws SQLException, InstantiationException, ParseException, IllegalAccessException {
        pathRel = PathTool.url_decode(pathRel);
        if (!pathRel.endsWith("/")) pathRel += '/';
        boolean isRootDir = StringUtils.equals(pathRel,"/");
        key = PathTool.url_decode(key);

        //f_pathRel = 'a' + f_nameLoc
        String pathRelSql = String.format("f_pathRel='%s'+f_nameLoc",pathRel);
        if(ConfigReader.dbType() != DataBaseType.SqlServer)
            pathRelSql = String.format("f_pathRel=CONCAT('%s',f_nameLoc)",pathRel);
        if(isRootDir) pathRelSql="";

        //从文件表中搜索
        List<FileInf> files = SqlTable.build("up6_files").reads(FileInf.build(),
                "f_id,f_pid,f_nameLoc,f_sizeLoc,f_lenLoc,f_time,f_pidRoot,f_fdTask,f_pathSvr,f_pathRel",
                SqlWhere.build()
                        .sql("f_pathRel",pathRelSql)
                        .sql("key",String.format("f_nameLoc like '%%%s%%'",key))
                        .eq("f_uid",uid)
                        .eq("f_complete",true)
                        .eq("f_deleted",false),
                SqlSort.build().desc("f_fdTask").desc("f_time")
        );

        //从目录表中搜索
        List<FileInf> fds = SqlTable.build("up6_folders").reads(FileInf.build(),
                "f_id,f_nameLoc,f_pid,f_sizeLoc,f_time,f_pidRoot,f_pathRel",
                SqlWhere.build()
                        .sql("f_pathRel",pathRelSql)
                        .sql("key",String.format("f_nameLoc like '%%%s%%'",key))
                        .eq("f_uid",uid)
                        .eq("f_complete",true)
                        .eq("f_deleted",false),
                SqlSort.build().desc("f_time")
        );

        for (FileInf f : fds)
        {
            f.fdTask=true;
            files.add(0,f);
        }

        JSONObject o = new JSONObject();
        o.put("count", files.size());
        o.put("code", 0);
        o.put("msg", "");
        o.put("data", JSONArray.fromObject(files.toArray(), JsonDateValueProcessor.build()));

        System.out.println(o.toString());
        return o.toString();
    }

    /**
     * 重命名文件或目录
     * @param id 文件或目录ID
     * @param fdTask 是否是文件夹
     * @param pathRel 相对路径
     * @param nameNew 新名称
     * @return
     */
    @RequestMapping(value="filemgr/rename",method = RequestMethod.GET)
    @ResponseBody
    public String rename(@RequestParam(value="id", required=false,defaultValue="")String id,
                         @RequestParam(value="fdTask", required=false,defaultValue="")Boolean fdTask,
                         @RequestParam(value="pathRel", required=false,defaultValue="")String pathRel,
                       @RequestParam(value="nameLoc", required=false,defaultValue="")String nameNew
    ) throws ParseException, IllegalAccessException, SQLException {
        id = id.trim();
        nameNew = PathTool.url_decode(nameNew);

        String parentDir = PathTool.getParent(pathRel);
        parentDir = parentDir.replace('\\', '/');
        //根目录
        boolean isRootDir = StringUtils.equals(parentDir,"/");

        //文件
        if(!fdTask) return this.rename_file(id,pathRel,nameNew);
        //子目录
        else if(!isRootDir) return this.renameChildDir(id,pathRel,nameNew);
        else return this.renameRootDir(id,pathRel,nameNew);
    }


    /**
     * 重命名文件
     * @param id      文件ID
     * @param pathRel 相对路径
     * @param name    文件名称
     * @return
     */
    public String rename_file(String id,String pathRel,String name) throws ParseException, IllegalAccessException, SQLException {
        //新的相对路径
        pathRel = PathTool.getParent(pathRel);
        pathRel = PathTool.combin(pathRel, name);

        //根据相对路径(新)=>查找同名文件
        FileInf s = SqlTable.build("up6_files").readOne(FileInf.build(),
                SqlWhere.build()
                        .eq("f_pathRel",pathRel)
                        .eq("f_deleted",false));

        boolean exist = s != null;

        //不存在同名文件
        if (!exist)
        {
            SqlTable.build("up6_files").update(
                    SqlSeter.build().set("f_nameLoc",name)
                            .set("f_nameSvr",name)
                            .set("f_pathRel",pathRel),
                    SqlWhere.build().eq("f_id",id)
            );

            JSONObject v = new JSONObject();
            v.put("state", true);
            v.put("pathRel",pathRel);
            return v.toString();
        }
        else
        {
            JSONObject v = new JSONObject();
            v.put("state", false);
            v.put("msg", "存在同名文件");
            v.put("code", "102");
            return v.toString();
        }
    }

    /**
     * 重命名根目录
     * @param id
     * @param pathRel
     * @param name
     * @return
     * @throws ParseException
     * @throws IllegalAccessException
     * @throws SQLException
     */
    public String renameRootDir(String id,String pathRel,String name) throws ParseException, IllegalAccessException, SQLException {
        String pathRelOld = pathRel;
        //新的相对路径
        String pathRelNew = "/" + name;
        FileInf s = SqlTable.build("up6_files").readOne(FileInf.build(),
                SqlWhere.build()
                        .eq("f_pathRel",pathRelNew)
                        .eq("f_deleted",false));

        boolean exist = s != null;

        //不存在同名目录
        if(!exist)
        {
            //更新文件夹相对路径，名称
            SqlTable.build("up6_files").update(
                    SqlSeter.build()
                            .set("f_nameLoc",name)
                            .set("f_nameSvr",name)
                            .set("f_pathRel",pathRelNew),
                    SqlWhere.build().eq("f_id",id)
            );

            DBFile.build().updatePathRel(pathRelOld, pathRelNew);
            DbFolder.build().updatePathRel(pathRelOld, pathRelNew);

            JSONObject v = new JSONObject();
            v.put("state", true);
            v.put("pathRel",pathRelNew);
            return v.toString();
        }//存在同名目录
        else
        {
            JSONObject res = new JSONObject();
            res.put("state", false);
            res.put("msg", "存在同名项");
            return  res.toString();
        }
    }

    /**
     * 重命名子目录
     * @param id
     * @param pathRel
     * @param name
     * @return
     * @throws ParseException
     * @throws IllegalAccessException
     * @throws SQLException
     */
    public String renameChildDir(String id,String pathRel,String name) throws ParseException, IllegalAccessException, SQLException {
        String pathRelOld = pathRel;
        //root/dir/name => root/dir
        Integer index = pathRel.lastIndexOf('/');
        pathRel = pathRel.substring(0, index + 1);
        //root/dir/old => root/dir/new
        pathRel += name;
        String pathRelNew = pathRel;

        FileInf fd = SqlTable.build("up6_folders").readOne(FileInf.build(),
                "f_pathRel",
                SqlWhere.build()
                        .eq("f_pathRel",pathRelNew)
                        .eq("f_deleted",false)
        );

        boolean exist = fd != null;
        //同名目录不存在=>可以重命名
        if(!exist)
        {
            //更新当前目录相对路径
            SqlTable.build("up6_folders").update(
                    SqlSeter.build()
                            .set("f_nameLoc",name)
                            .set("f_pathRel",pathRelNew),
                    SqlWhere.build().eq("f_id",id)
            );

            //更新子文件和子目录相对路径
            DBFile.build().updatePathRel(pathRelOld, pathRelNew);
            DbFolder.build().updatePathRel(pathRelOld, pathRelNew);

            JSONObject v = new JSONObject();
            v.put("state", true);
            v.put("pathRel",pathRelNew);
            return v.toString();

        }//存在同名目录
        else{
            JSONObject v = new JSONObject();
            v.put("state", false);
            v.put("msg", "存在同名目录");
            v.put("code", "102");
            return v.toString();
        }
    }

    /**
     * 删除文件或目录
     * @param id 文件ID
     * @return
     */
    @RequestMapping(value="filemgr/del",method = RequestMethod.GET)
    @ResponseBody
    public String del(@RequestParam(value="id", required=false,defaultValue="")String id,
                      @RequestParam(value="pathRel", required=false,defaultValue="")String pathRel
    )
    {
        pathRel = PathTool.url_decode(pathRel);
        pathRel += '/';

        SqlWhereMerge swm = new SqlWhereMerge();
        DBConfig cfg = new DBConfig();
        if(StringUtils.equals(cfg.m_db, "sql"))
        {
            swm.charindex(pathRel,"f_pathRel");
        }
        else
        {
            swm.instr(pathRel,"f_pathRel");
        }
        String where = swm.to_sql();

        SqlExec se = new SqlExec();
        se.update("up6_files", new SqlParam[] {new SqlParam("f_deleted",true)}, where);
        se.update("up6_files"
                , new SqlParam[] {new SqlParam("f_deleted",true)}
                , new SqlParam[] {new SqlParam("f_id",id)}
        );
        se.update("up6_folders", new SqlParam[] {new SqlParam("f_deleted",true)}, where);
        se.update("up6_folders"
                , new SqlParam[] {new SqlParam("f_deleted",true)}
                , new SqlParam[] {new SqlParam("f_id",id)}
        );

        JSONObject ret = new JSONObject();
        ret.put("ret", 1);
        return ret.toString();
    }

    /**
     * 批量删除
     * @param data
     * @return
     */
    @RequestMapping(value="filemgr/del-batch",method = RequestMethod.GET)
    @ResponseBody
    public String del_batch(@RequestParam(value="data", required=false,defaultValue="")String data
    )
    {
        data = PathTool.url_decode(data);
        JSONArray o = JSONArray.fromObject(data);

        SqlExec se = new SqlExec();
        se.exec_batch("up6_files", "update up6_files set f_deleted=1 where f_id=?", "", "f_id", o);
        se.exec_batch("up6_folders", "update up6_folders set f_deleted=1 where f_id=?", "", "f_id", o);

        JSONObject ret = new JSONObject();
        ret.put("ret", 1);
        return ret.toString();
    }

    /**
     * 获取当前目录路径
     * @param data
     * @return
     */
    @RequestMapping(value="filemgr/path",method = RequestMethod.GET)
    @ResponseBody
    public String path(@RequestParam(value="data", required=false,defaultValue="")String data
    )
    {
        data = PathTool.url_decode(data);
        JSONObject fd = JSONObject.fromObject(data);

        DbFolder df = new DbFolder();
        return df.build_path(fd).toString();
    }

    /**
     * 加载树
     * @param pid
     * @return
     */
    @RequestMapping(value="filemgr/tree",method = RequestMethod.GET)
    @ResponseBody
    public String tree(@RequestParam(value="pid", required=false,defaultValue="")String pid
    )
    {
        SqlWhereMerge swm = new SqlWhereMerge();
        swm.equal("f_fdChild", false);
        swm.equal("f_fdTask", true);
        swm.equal("f_deleted", false);
        if (!StringUtils.isBlank(pid)) swm.equal("f_pid", pid);

        SqlExec se = new SqlExec();
        JSONArray arr = new JSONArray();
        JSONArray data = se.select("up6_files"
                , "f_id,f_pid,f_pidRoot,f_nameLoc"
                , swm.to_sql()
                ,"");

        //查子目录
        if (!StringUtils.isBlank(pid))
        {
            data = se.select("up6_folders"
                    , "f_id,f_pid,f_pidRoot,f_nameLoc"
                    , new SqlParam[] {
                            new SqlParam("f_pid", pid)
                            ,new SqlParam("f_deleted", false)
                    },"");
        }

        for(int i = 0 , l = data.size() ; i<l;++i)
        {
            JSONObject item = new JSONObject();
            JSONObject f = (JSONObject)data.get(i);
            item.put("id", f.getString("f_id") );
            item.put("text", f.getString("f_nameLoc"));
            item.put("parent", "#");
            item.put("nodeSvr", f);
            arr.add(item);
        }
        return arr.toString();
    }

    /**
     * 文件初始化，在上传文件前调用，前端调用
     * @param pid 父ID
     * @param pidRoot 根ID
     * @param id 文件ID
     * @param md5 文件MD5
     * @param uid 用户ID
     * @param lenLoc 数字化的本地文件大小 1024
     * @param sizeLoc 格式化的本地文件大小 10MB
     * @param callback jq回调方法，提供跨域调用
     * @param pathLoc 本地文件路径 c:\\file.txt
     * @param pathRel 文件相对路径。/root/file.txt
     * @return
     */
    @RequestMapping(value="filemgr/f_create",method = RequestMethod.GET)
    @ResponseBody
    public String f_create(@RequestParam(value="pid", required=false,defaultValue="")String pid,
                           @RequestParam(value="pidRoot", required=false,defaultValue="")String pidRoot,
                           @RequestParam(value="id", required=false,defaultValue="")String id,
                           @RequestParam(value="md5", required=false,defaultValue="")String md5,
                           @RequestParam(value="uid", required=false,defaultValue="0")Integer uid,
                           @RequestParam(value="lenLoc", required=false,defaultValue="")String lenLoc,
                           @RequestParam(value="sizeLoc", required=false,defaultValue="")String sizeLoc,
                           @RequestParam(value="blockSize", required=false,defaultValue="0")String blockSize,
                           @RequestParam(value="callback", required=false,defaultValue="")String callback,
                           @RequestParam(value="pathLoc", required=false,defaultValue="")String pathLoc,
                           @RequestParam(value="pathRel", required=false,defaultValue="")String pathRel
    ) throws ParseException, IllegalAccessException, SQLException {
        if(StringUtils.isBlank(pidRoot)) pidRoot = pid;//当前文件夹是根目录
        pathLoc	= PathTool.url_decode(pathLoc);
        pathRel = PathTool.url_decode(pathRel);

        //参数为空
        if (	StringUtils.isBlank(md5)&&
                StringUtils.isBlank(sizeLoc))
        {
            return callback + "({\"value\":null})";
        }

        FileInf fileSvr= new FileInf();
        fileSvr.id = id;
        fileSvr.pid = pid;
        fileSvr.pidRoot = pidRoot;
        boolean isRootFile = StringUtils.equals(pathRel,"/");
        fileSvr.fdChild = !isRootFile;
        fileSvr.uid = uid;
        fileSvr.nameLoc = PathTool.getName(pathLoc);
        fileSvr.pathLoc = pathLoc;
        fileSvr.pathRel = PathTool.combine(pathRel, fileSvr.nameLoc);
        fileSvr.lenLoc = Long.parseLong(lenLoc);
        fileSvr.calLenLocSec();//计算文件加密后的大小
        fileSvr.sizeLoc = sizeLoc;
        fileSvr.deleted = false;
        fileSvr.md5 = md5;
        fileSvr.blockSize=Integer.parseInt(blockSize);
        fileSvr.nameSvr = fileSvr.nameLoc;

        //所有单个文件均以uuid/file方式存储
        PathBuilderUuid pb = new PathBuilderUuid();
        try {
            fileSvr.pathSvr = pb.genFile(fileSvr.uid,fileSvr);
        } catch (IOException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }
        fileSvr.pathSvr = fileSvr.pathSvr.replace("\\","/");


        //同名文件检测
		/*DbFolder df = new DbFolder();
		if (df.exist_same_file(fileSvr.nameLoc,pid))
		{
		    String data = callback + "({'value':'','ret':false,'code':'101'})";
		    this.m_wb.toContent(data);
		    return;
		}*/

        DBFile db = DBFile.build();
        FileInf fileExist = db.exist_file(md5);
        //数据库已存在相同文件，且有上传进度，则直接使用此信息
        if(fileExist!=null)
        {
            fileSvr.nameSvr			= fileExist.nameSvr;
            fileSvr.pathSvr 		= fileExist.pathSvr;
            fileSvr.perSvr 			= fileExist.perSvr;
            fileSvr.lenSvr 			= fileExist.lenSvr;
            fileSvr.complete		= fileExist.complete;
            db.Add(fileSvr);

            //触发事件
            up6_biz_event.file_create_same(fileSvr);
        }//此文件不存在
        else
        {
            FileBlockWriter fw = ConfigReader.blockWriter();
            try {
                fileSvr.object_id = fw.make(fileSvr);
                fileSvr.object_key = fileSvr.getObjectKey();
            } catch (IOException e) {
                e.printStackTrace();
                res.setStatus(500);
                return  e.toString();
            }

            db.Add(fileSvr);
            //触发事件
            up6_biz_event.file_create(fileSvr);
        }

        //传输加密
        if (ConfigReader.postEncrypt())
        {
            CryptoTool ct   = new CryptoTool();
            try{
                fileSvr.pathSvr = ct.encrypt(fileSvr.pathSvr);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        Gson gson = new Gson();
        String json = gson.toJson(fileSvr);

        try {
            json = URLEncoder.encode(json,"UTF-8");
        } catch (UnsupportedEncodingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }//编码，防止中文乱码
        json = json.replace("+","%20");
        json = callback + "({\"value\":\"" + json + "\",\"ret\":true})";//返回jsonp格式数据。
        return json;
    }
    /**
     * 文件上传完毕，在文件上传完毕后由前端调用。
     * 调用位置：up6.file.js-post_complete
     * @param id 文件ID，由控件生成，GUID 示例：04fdfc13fc2a4b7a9d0682f8c344926f
     * @param uid 用户ID，在JS中困于
     * @param md5 文件MD5
     * @param pid 文件PID
     * @param callback JQ回调
     * @param nameLoc 文件名称，由控件提供
     * @return
     */
    @RequestMapping(value="filemgr/f_complete",method = RequestMethod.GET)
    @ResponseBody
    public String f_complete(@RequestParam(value="id", required=false,defaultValue="")String id,
                             @RequestParam(value="uid", required=false,defaultValue="0")Integer uid,
                             @RequestParam(value="md5", required=false,defaultValue="")String md5,
                             @RequestParam(value="pid", required=false,defaultValue="")String pid,
                             @RequestParam(value="callback", required=false,defaultValue="")String callback,
                             @RequestParam(value="cover", required=false,defaultValue="0")Integer cover,
                             @RequestParam(value="nameLoc", required=false,defaultValue="")String nameLoc) throws ParseException, IllegalAccessException, SQLException {
        nameLoc	= PathTool.url_decode(nameLoc);
        //返回值。1表示成功
        int ret = 0;
        if ( !StringUtils.isBlank(id))
        {
            DBFile db = DBFile.build();
            db.complete(id,uid);
            FileInf file = db.read(id);

            //覆盖同名文件-更新同名文件状态
            if(cover == 1) db.delete(file.pathRel, uid, id);

            up6_biz_event.file_post_complete(id);
            ret = 1;
        }
        return callback + "(" + ret + ")";
    }

    /**
     * 文件夹初始化，上传文件夹前调用。
     * @param pid
     * @param pidRoot
     * @param id
     * @param md5
     * @param uid
     * @param lenLoc
     * @param sizeLoc
     * @param callback
     * @param pathLoc
     * @param pathRel
     * @return
     */
    @RequestMapping(value="filemgr/fd_create",method = RequestMethod.GET)
    @ResponseBody
    public String fd_create(@RequestParam(value="pid", required=false,defaultValue="")String pid,
                           @RequestParam(value="pidRoot", required=false,defaultValue="")String pidRoot,
                           @RequestParam(value="id", required=false,defaultValue="")String id,
                           @RequestParam(value="md5", required=false,defaultValue="")String md5,
                           @RequestParam(value="uid", required=false,defaultValue="0")Integer uid,
                           @RequestParam(value="lenLoc", required=false,defaultValue="")String lenLoc,
                           @RequestParam(value="sizeLoc", required=false,defaultValue="")String sizeLoc,
                           @RequestParam(value="callback", required=false,defaultValue="")String callback,
                           @RequestParam(value="pathLoc", required=false,defaultValue="")String pathLoc,
                           @RequestParam(value="pathRel", required=false,defaultValue="")String pathRel
    ) throws ParseException, IllegalAccessException, SQLException {

        if( StringUtils.isBlank(pidRoot)) pidRoot = pid;//父目录是根目录
        pathRel = PathTool.url_decode(pathRel);
        pathLoc	= PathTool.url_decode(pathLoc);

        //参数为空
        if (    StringUtils.isBlank(id)||
                StringUtils.isBlank(pathLoc))
        {
            return callback + "({\"value\":null})";
        }

        FileInf fileSvr = new FileInf();
        fileSvr.id      = id;
        fileSvr.pid     = pid;
        fileSvr.pidRoot = pidRoot;
        fileSvr.fdChild = false;
        fileSvr.fdTask  = true;
        fileSvr.uid     = uid;
        fileSvr.nameLoc = PathTool.getName(pathLoc);
        fileSvr.pathLoc = pathLoc;
        fileSvr.pathRel = PathTool.combine(pathRel, fileSvr.nameLoc);
        fileSvr.lenLoc  = Long.parseLong(lenLoc);
        fileSvr.sizeLoc = sizeLoc;
        fileSvr.deleted = false;
        fileSvr.nameSvr = fileSvr.nameLoc;

        //检查同名目录
		/*DbFolder df = new DbFolder();
		if (df.exist_same_folder(fileSvr.nameLoc, pid))
		{
			JSONObject o = new JSONObject();
			o.put("value","");
			o.put("ret", false);
			o.put("code", "102");
		    String js = callback + String.format("(%s)", o.toString());
		    this.m_wb.toContent(js);
		    return;
		}*/

        //生成存储路径
        PathBuilderUuid pb = new PathBuilderUuid();
        try {
            fileSvr.pathSvr = pb.genFolder(fileSvr);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        fileSvr.pathSvr = fileSvr.pathSvr.replace("\\","/");
        PathTool.createDirectory(fileSvr.pathSvr);

        //创建层级结构
        FolderSchema fst = new FolderSchema();
        if(!fst.create(fileSvr))
        {
            res.setStatus(500);;
            return "save folder schema error";
        }

        //添加到数据表
        DBConfig cfg = new DBConfig();
        DBFile db = cfg.db();
        if(StringUtils.equals(pathRel,"/")) db.Add(fileSvr);
        else db.addFolderChild(fileSvr);

        //传输加密
        if (ConfigReader.postEncrypt())
        {
            CryptoTool ct   = new CryptoTool();
            try{
                fileSvr.pathSvr = ct.encrypt(fileSvr.pathSvr);
            }
            catch (Exception e) {
                e.printStackTrace();
            }
        }

        up6_biz_event.folder_create(fileSvr);

        Gson g = new Gson();
        String json = g.toJson(fileSvr);
        try {
            json = URLEncoder.encode(json,"utf-8");
        } catch (UnsupportedEncodingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        json = json.replace("+","%20");

        JSONObject ret = new JSONObject();
        ret.put("value",json);
        ret.put("ret",true);
        json = callback + String.format("(%s)",ret.toString());//返回jsonp格式数据。
        return json;
    }


    /**
     * 文件夹上传完毕，文件夹上传结束后调用
     * @return
     */
    @RequestMapping(value="filemgr/fd_complete",method = RequestMethod.GET)
    @ResponseBody
    public String fd_complete(
            @RequestParam(value="id", required=false,defaultValue="")String id,
            @RequestParam(value="pid", required=false,defaultValue="")String pid,
            @RequestParam(value="pathRel", required=false,defaultValue="")String pathRel,
            @RequestParam(value="uid", required=false,defaultValue="0")Integer uid,
            @RequestParam(value="callback", required=false,defaultValue="")String cbk,
            @RequestParam(value="cover", required=false,defaultValue="0")Integer cover
    ) throws IOException, SQLException, ParseException, IllegalAccessException {
        int ret = 0;

        //参数为空
        if (	!StringUtils.isBlank(id))
        {
            pathRel = PathTool.url_decode(pathRel);
            //是根目录
            boolean isRootDir = StringUtils.equals(pathRel,"/");
            FileInf folder = null;
            FileInf fdExist = null;

            //子目录
            if(!isRootDir)
            {
                folder = DbFolder.build().read(id);
                fdExist = DbFolder.build().read(folder.pathRel,id);

                //存在相同目录=>删除旧目录
                if(fdExist != null) DbFolder.build().del(fdExist.id,uid);
            }//根目录
            else{
                folder = DBFile.build().read(id);
                fdExist = DBFile.build().read(folder.pathRel,id,uid);

                //存在相同目录=>删除旧目录
                if(fdExist != null) DBFile.build().Delete(uid,fdExist.id);
            }

            if(fdExist !=null)
            {
                folder.id = fdExist.id;
                folder.pid = fdExist.pid;
                folder.pidRoot = fdExist.pidRoot;
            }

            //根节点
            FileInf root = new FileInf();
            root.id = folder.pidRoot;
            root.uid = folder.uid;
            //当前节点是根节点
            if( StringUtils.isBlank(root.id)) root.id = folder.id;

            //从文件中解析层级结构信息
            FolderScaner fsd = new FolderScaner();
            //覆盖已有项
            fsd.m_cover = fdExist!=null;
            fsd.save(folder);

            //子目录上传完毕
            if(!isRootDir) DbFolder.build().complete(id);
            //根目录
            else DBFile.build().complete(id,uid);

            up6_biz_event.folder_post_complete(id);

            ret = 1;
        }
        return cbk + "(" + ret + ")";
    }

    /**
     * 获取文件夹数据，
     * @param id
     * @param callback
     * @return
     */
    @RequestMapping(value="filemgr/fd_data",method = RequestMethod.GET)
    @ResponseBody
    public String fd_data(@RequestParam(value="id", required=false,defaultValue="")String id,
                            @RequestParam(value="callback", required=false,defaultValue="")String callback
    )
    {

        if (StringUtils.isBlank(id))
        {
            return callback + "({\"value\":null})";
        }

        FolderBuilder fb = new FolderBuilder();
        Gson gson = new Gson();
        String json = gson.toJson(fb.build(id));

        try {
            json = URLEncoder.encode(json,"UTF-8");
        } catch (UnsupportedEncodingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }//编码，防止中文乱码
        json = json.replace("+","%20");
        json = callback + "({\"value\":\"" + json + "\"})";//返回jsonp格式数据。
        return json;
    }

    /**
     * 创建目录，
     * @param name 目录名称
     * @param pid 父级ID
     * @param uid 用户ID
     * @param pidRoot 根ID
     * @param pathRel 相对路径,/test/test1
     * @return
     */
    @RequestMapping(value="filemgr/mk_folder",method = RequestMethod.GET)
    @ResponseBody
    public String mk_folder(@RequestParam(value="nameLoc", required=false,defaultValue="")String name,
                            @RequestParam(value="pid", required=false,defaultValue="")String pid,
                            @RequestParam(value="uid", required=false,defaultValue="")Integer uid,
                            @RequestParam(value="pidRoot", required=false,defaultValue="")String pidRoot,
                            @RequestParam(value="pathRel", required=false,defaultValue="")String pathRel
    ) throws ParseException, IllegalAccessException, SQLException {
        name = PathTool.url_decode(name);
        pathRel = PathTool.url_decode(pathRel);
        boolean isRootDir = StringUtils.equals(pathRel,"/");
        pathRel = PathTool.combine(pathRel, name);

        DbFolder df = DbFolder.build();
        if (df.exist_same_folder(pathRel))
        {
            JSONObject ret = new JSONObject();
            ret.put("ret", false);
            ret.put("msg", "已存在同名目录");
            return ret.toString();
        }

        FileInf dir = new FileInf();
        dir.id = PathTool.guid();
        dir.pid = pid;
        dir.uid = uid;
        dir.pidRoot = pidRoot;
        dir.nameLoc = name;
        dir.nameSvr = name;
        dir.complete = true;
        dir.fdTask = true;
        dir.pathRel = pathRel;

        //根目录
        if (isRootDir)
        {
            DBFile.build().Add(dir);
        }//子目录
        else
        {
            DbFolder.build().add(dir);
        }
        JSONObject ret = JSONObject.fromObject(dir);
        ret.put("ret", true);
        return ret.toString();
    }

    /**
     * 加载未上传完的数据
     * @param uid
     * @return
     */
    @RequestMapping(value="filemgr/uncomp",method = RequestMethod.GET)
    @ResponseBody
    public String uncomp(@RequestParam(value="uid", required=false,defaultValue="0")Integer uid) throws SQLException, InstantiationException, ParseException, IllegalAccessException {
        return DBFile.build().unCompletes(uid);
    }

    /**
     * 加载未下载完的数据
     * @param uid
     * @return
     */
    @RequestMapping(value="filemgr/uncmp_down",method = RequestMethod.GET)
    @ResponseBody
    public String uncmp_down(@RequestParam(value="uid", required=false,defaultValue="0")Integer uid) throws SQLException, InstantiationException, ParseException, IllegalAccessException {
        return DnFile.build().all_uncmp(uid);
    }
}
